home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / -archivi / -recent2 / amhelios.lha / AmHelios / view_sys.cpp < prev    next >
C/C++ Source or Header  |  1997-08-24  |  12KB  |  410 lines

  1. ////////////////////////////////////////////////////////////
  2. //
  3. //  VIEW_SYS.CPP - Viewing System Class
  4. //
  5. //  Version:    1.03A
  6. //
  7. //  History:    94/08/23 - Version 1.00A release.
  8. //              94/12/16 - Version 1.01A release.
  9. //              94/12/24 - Modified BuildTransform to
  10. //                         include parallel projection and
  11. //                         and window scale.
  12. //                       - Modified BackFaceCull to include
  13. //                         parallel projection.
  14. //              95/02/05 - Version 1.02A release.
  15. //              95/07/21 - Version 1.02B release.
  16. //              96/02/14 - Version 1.02C release.
  17. //              96/03/30 - Added Dolly, Orbit, Pan, Rotate,
  18. //                         Tilt, Zoom, SetEyeFocusPosn and
  19. //                         InitViewSystem functions.
  20. //                       - Modified BuildTransform to
  21. //                         calculate view-up vector.
  22. //                       - Modified SetViewUp to calculate
  23. //                         canonical view-up vector.
  24. //              96/04/01 - Version 1.03A release.
  25. //
  26. //  Compilers:  Microsoft Visual C/C++ Professional V1.5
  27. //              Borland C++ Version 4.5
  28. //
  29. //  Author:     Ian Ashdown, P.Eng.
  30. //              byHeart Software Limited
  31. //              620 Ballantree Road
  32. //              West Vancouver, B.C.
  33. //              Canada V7S 1W3
  34. //              Tel. (604) 922-6148
  35. //              Fax. (604) 987-7621
  36. //
  37. //  Copyright 1994-1996 byHeart Software Limited
  38. //
  39. //  The following source code has been derived from:
  40. //
  41. //    Ashdown, I. 1994. Radiosity: A Programmer's
  42. //    Perspective. New York, NY: John Wiley & Sons.
  43. //
  44. //  It may be freely copied, redistributed, and/or modified
  45. //  for personal use ONLY, as long as the copyright notice
  46. //  is included with all source code files.
  47. //
  48. ////////////////////////////////////////////////////////////
  49.  
  50. #include "view_sys.h"
  51.  
  52. // Build projective transformation matrix and eye position
  53. void ViewSys::BuildTransform()
  54. {
  55.   double rn;            // Translation factor
  56.   double su, sv, sn;    // Scaling factors
  57.   Vector3 o;            // Origin vector
  58.   Vector3 u;            // u-axis vector
  59.  
  60.   // Calculate view-up vector
  61.   vuv = cos(tilt_angle) * cvu - sin(tilt_angle) *
  62.       Cross(vdv, cvu);
  63.  
  64.   // Set view space origin
  65.   origin.SetX(eye_posn.GetX() - eye * vdv.GetX());
  66.   origin.SetY(eye_posn.GetY() - eye * vdv.GetY());
  67.   origin.SetZ(eye_posn.GetZ() - eye * vdv.GetZ());
  68.  
  69.   o = Vector3(origin);  // Initialize origin vector
  70.   u = Cross(vdv, vuv);  // Calculate u-axis vector
  71.  
  72.   // Initialize view transformation matrix
  73.   ptm[0][0] = u.GetX();
  74.   ptm[0][1] = u.GetY();
  75.   ptm[0][2] = u.GetZ();
  76.   ptm[0][3] = -(Dot(o, u));
  77.  
  78.   ptm[1][0] = vuv.GetX();
  79.   ptm[1][1] = vuv.GetY();
  80.   ptm[1][2] = vuv.GetZ();
  81.   ptm[1][3] = -(Dot(o, vuv));
  82.  
  83.   ptm[2][0] = vdv.GetX();
  84.   ptm[2][1] = vdv.GetY();
  85.   ptm[2][2] = vdv.GetZ();
  86.   ptm[2][3] = -(Dot(o, vdv));
  87.  
  88.   ptm[3][0] = 0.0;
  89.   ptm[3][1] = 0.0;
  90.   ptm[3][2] = 0.0;
  91.   ptm[3][3] = 1.0;
  92.  
  93.   if (par_flag == FALSE)        // Perspective projection ?
  94.   {
  95.     // Premultiply by perspective transformation matrix
  96.     ptm[3][0] -= ptm[2][0] / eye;
  97.     ptm[3][1] -= ptm[2][1] / eye;
  98.     ptm[3][2] -= ptm[2][2] / eye;
  99.     ptm[3][3] -= ptm[2][3] / eye;
  100.   }
  101.  
  102.   // Premultiply by normalization matrix
  103.   if (aspect >= 1.0)
  104.   {
  105.     su = 0.5 * scale;
  106.     sv = 0.5 * scale * aspect;
  107.   }
  108.   else
  109.   {
  110.     su = 0.5 * scale / aspect;
  111.     sv = 0.5 * scale;
  112.   }
  113.  
  114.   sn = (eye - bpd) * (eye - fpd) / (eye * eye * (bpd -
  115.       fpd));
  116.   rn = fpd * (eye - bpd) / (eye * (fpd - bpd));
  117.  
  118.   ptm[0][0] = su * ptm[0][0] + 0.5 * ptm[3][0];
  119.   ptm[0][1] = su * ptm[0][1] + 0.5 * ptm[3][1];
  120.   ptm[0][2] = su * ptm[0][2] + 0.5 * ptm[3][2];
  121.   ptm[0][3] = su * ptm[0][3] + 0.5 * ptm[3][3];
  122.  
  123.   ptm[1][0] = sv * ptm[1][0] + 0.5 * ptm[3][0];
  124.   ptm[1][1] = sv * ptm[1][1] + 0.5 * ptm[3][1];
  125.   ptm[1][2] = sv * ptm[1][2] + 0.5 * ptm[3][2];
  126.   ptm[1][3] = sv * ptm[1][3] + 0.5 * ptm[3][3];
  127.  
  128.   ptm[2][0] = sn * ptm[2][0] + rn * ptm[3][0];
  129.   ptm[2][1] = sn * ptm[2][1] + rn * ptm[3][1];
  130.   ptm[2][2] = sn * ptm[2][2] + rn * ptm[3][2];
  131.   ptm[2][3] = sn * ptm[2][3] + rn * ptm[3][3];
  132. }
  133.  
  134. // Set view-up vector
  135. void ViewSys::SetViewUp( Vector3 &approx )
  136. {
  137.   Vector3 temp = vdv;   // Temporary vector
  138.  
  139.   // Project approximate view-up vector onto view plane
  140.   temp *= Dot(approx, vdv);
  141.   cvu = approx - temp;
  142.  
  143.   cvu.Norm();   // Normalize canonical view-up vector
  144. }
  145.  
  146. // Perform backface culling
  147. BOOL ViewSys::BackFaceCull( Patch3 *ppatch )
  148. {
  149.   Vector3 view;         // View vector
  150.  
  151.   if (par_flag == FALSE)     // Perpective projection ?
  152.   {
  153.     // Calculate view vector (first vertex to eye position)
  154.     view = Vector3(ppatch->GetVertexPtr(0)->GetPosn(),
  155.         eye_posn);
  156.  
  157.     // Indicate whether patch is backface
  158.     return (Dot(ppatch->GetNormal(), view) < MIN_VALUE) ?
  159.         TRUE : FALSE;
  160.   }
  161.   else  // Parallel projection
  162.   {
  163.     // Indicate whether patch is backface
  164.     return (Dot(ppatch->GetNormal(), vdv) > MIN_VALUE) ?
  165.         TRUE : FALSE;
  166.   }
  167. }
  168.  
  169. // Initialize view system parameters
  170. void ViewSys::InitViewSystem( Environ *penv )
  171. {
  172.   double dx, dy, dz;    // Extent deltas
  173.   Point3 focus;         // Focus position
  174.   Vector3 temp;         // Temporary vector
  175.  
  176.   // Calculate extent deltas
  177.   dx = penv->GetMax_X() - penv->GetMin_X();
  178.   dy = penv->GetMax_Y() - penv->GetMin_Y();
  179.   dz = penv->GetMax_Z() - penv->GetMin_Z();
  180.  
  181.   // Determine default view
  182.   fpd = -1.99;
  183.   bpd = 10000.0;
  184.   scale = 1.0;
  185.   tilt_angle = 0.0;
  186.   par_flag = FALSE;
  187.  
  188.   if (dy > (dz * aspect))
  189.     eye_posn.SetX((dy / VS_FILL_FACTOR) + penv->GetMax_X());
  190.   else
  191.     eye_posn.SetX(((dz * aspect) / VS_FILL_FACTOR) +
  192.         penv->GetMax_X());
  193.   eye_posn.SetY(dy / 2.0 + penv->GetMin_Y());
  194.   eye_posn.SetZ(dz / 2.0 + penv->GetMin_Z());
  195.  
  196.   focus_posn.SetX(dx / 2.0 + penv->GetMin_X());
  197.   focus_posn.SetY(dy / 2.0 + penv->GetMin_Y());
  198.   focus_posn.SetZ(dz / 2.0 + penv->GetMin_Z());
  199.  
  200.   temp = focus_posn - eye_posn;
  201.   efd = temp.Length();
  202.  
  203.   vdv = Vector3(-1.0, 0.0, 0.0);
  204.   cvu = Vector3(0.0, 0.0, -1.0);
  205.   vuv = Vector3(0.0, 0.0, 1.0);
  206.   eye = -2.0;
  207.  
  208.   // Update view system parameters
  209.   BuildTransform();
  210. }
  211.  
  212. void ViewSys::SetEyeFocusPosn( Point3 &e, Point3 &f )
  213. {
  214.   Vector3 hn, hv;       // Horizontal projection vectors
  215.   Vector3 temp;         // Temporary vector
  216.   Vector3 u, v, n;      // Viewing system coordinate axes
  217.  
  218.   n = vdv;  // Save current view director vector
  219.   v = cvu;  // Save current canonical view-up vector
  220.  
  221.   u = Cross(n, v);      // Calculate u-axis vector
  222.  
  223.   // Update eye and focus positions
  224.   eye_posn = e;
  225.   focus_posn = f;
  226.  
  227.   // Update eye-focus distance
  228.   temp = focus_posn - eye_posn;
  229.   efd = temp.Length();
  230.  
  231.   // Update view direction vector
  232.   vdv = temp.Norm();
  233.  
  234.   // Project view direction vectors onto horizontal plane
  235.   hn = Vector3(n.GetX(), n.GetY(), 0.0);
  236.   hv = Vector3(vdv.GetX(), vdv.GetY(), 0.0);
  237.  
  238.   // Update u-axis vector
  239.   if (hv.Length() > MIN_VALUE)
  240.   {
  241.     // NOTE: If the camera was previously oriented facing
  242.     //       straight up, the canonical view-up vector will
  243.     //       be oriented upwards, regardless of its previous
  244.     //       orientation.
  245.     if (cvu.GetZ() > -MIN_VALUE)
  246.     {
  247.       u.SetX(hv.GetY());
  248.       u.SetY(-hv.GetX());
  249.     }
  250.     else
  251.     {
  252.       u.SetX(-hv.GetY());
  253.       u.SetY(hv.GetX());
  254.     }
  255.   }
  256.  
  257.   // Calculate approximate view-up vector
  258.   temp = Cross(u, vdv);
  259.  
  260.   SetViewUp(temp);  // Set view-up vector
  261.  
  262.   // Update view system parameters
  263.   BuildTransform();
  264. }
  265.  
  266. // Dolly viewing system along view direction vector
  267. void ViewSys::Dolly( double dist_mult )
  268. {
  269.   Vector3 dolly_delta;  // Dolly delta vector
  270.  
  271.   // Calculate dolly delta vector
  272.   dolly_delta = vdv * efd * dist_mult;
  273.  
  274.   // Update eye and focus positions
  275.   eye_posn = eye_posn + dolly_delta;
  276.   focus_posn = focus_posn + dolly_delta;
  277.  
  278.   // Update view system parameters
  279.   BuildTransform();
  280. }
  281.  
  282. // Orbit viewing system about focus position (where "horz"
  283. // and "vert" rotation angles are in radians)
  284. void ViewSys::Orbit( double horz, double vert )
  285. {
  286.   // Move eye position to focus position
  287.   Dolly(1.0);
  288.  
  289.   // Rotate viewing system about focus position
  290.   Rotate(-horz, -vert);
  291.  
  292.   // Update eye position
  293.   Dolly(-1.0);
  294. }
  295.  
  296. // Pan viewing system perpendicular to view direction vector
  297. void ViewSys::Pan( double horz_mult, double vert_mult )
  298. {
  299.   Vector3 pan_delta;    // Pan delta vector
  300.  
  301.   // Calculate pan delta vector
  302.   pan_delta = Cross(vdv, cvu) *  horz_mult * efd + cvu *
  303.       vert_mult * efd;
  304.  
  305.   // Update eye and focus positions
  306.   eye_posn = eye_posn + pan_delta;
  307.   focus_posn = focus_posn + pan_delta;
  308.  
  309.   // Update view system parameters
  310.   BuildTransform();
  311. }
  312.  
  313. // Rotate viewing system about eye position (where "horz"
  314. // and "vert" rotation angles are in radians)
  315. void ViewSys::Rotate( double horz, double vert )
  316. {
  317.   double x, y;      // Horizontal plane coordinates
  318.   Vector3 approx;   // Approximate view-up vector
  319.   Vector3 u, v, n;  // Viewing system coordinate axes
  320.  
  321.   // Get viewing system cooordinate axes
  322.   u = Cross(vdv, cvu);
  323.   v = cvu;
  324.   n = vdv;
  325.  
  326.   // Rotate view direction vector vertically through local
  327.   // u-axis
  328.   vdv = cos(vert) * n + sin(vert) * v;
  329.  
  330.   // Rotate view direction vector horizontally through
  331.   // global z-axis
  332.   x = vdv.GetX();
  333.   y = vdv.GetY();
  334.   vdv.SetX(cos(horz) * x + sin(horz) * y);
  335.   vdv.SetY(cos(horz) * y - sin(horz) * x);
  336.   vdv.Norm();
  337.  
  338.   // Rotate u-axis horizontally through global z-axis
  339.   x = u.GetX();
  340.   y = u.GetY();
  341.   u.SetX(cos(horz) * x + sin(horz) * y);
  342.   u.SetY(cos(horz) * y - sin(horz) * x);
  343.  
  344.   // Calculate approximate view-up vector
  345.   approx = Cross(u, vdv);
  346.  
  347.   SetViewUp(approx);    // Set view-up vector
  348.  
  349.   // Update focus position
  350.   focus_posn = eye_posn + vdv * efd;
  351.  
  352.   // Update view system parameters
  353.   BuildTransform();
  354. }
  355.  
  356. // Tilt viewing system view-up vector (where "tilt" angle is
  357. // in radians)
  358. void ViewSys::Tilt( double tilt )
  359. {
  360.   tilt_angle += tilt;   // Update tilt angle
  361.  
  362.   // Limit tilt angle range
  363.   if (tilt_angle >= 2.0 * PI)
  364.     tilt_angle -= 2.0 * PI;
  365.   else if (tilt_angle < 0.0)
  366.     tilt_angle += 2.0 * PI;
  367.  
  368.   // Update view system parameters
  369.   BuildTransform();
  370. }
  371.  
  372. // Zoom viewing system field of view
  373. void ViewSys::Zoom( double vd_mult )
  374. {
  375.   double vd_delta;  // View distance delta
  376.  
  377.   // Calculate view distance delta
  378.   vd_delta = -eye * (1.0 - vd_mult);
  379.  
  380.   // Update view distance
  381.   eye *= vd_mult;
  382.  
  383.   // Update clipping plane distances
  384.   fpd += vd_delta;
  385.   bpd += vd_delta;
  386.  
  387.   // Update view system parameters
  388.   BuildTransform();
  389. }
  390.  
  391. // Move eye and focus position along view direction vector
  392. void ViewSys::DollyEyeFocusPosn( double eye_mult, double focus_mult )
  393. {
  394.   Vector3 eye_delta, focus_delta;  // Move delta vector
  395.   Vector3 temp;                    // Temporary vector
  396.  
  397.   // Calculate move delta vector
  398.   eye_delta = vdv * efd * eye_mult;
  399.   focus_delta = vdv * efd * focus_mult;
  400.  
  401.   // Update eye and focus positions
  402.   eye_posn = eye_posn + eye_delta;
  403.   focus_posn = focus_posn + focus_delta;
  404.   temp = focus_posn - eye_posn;
  405.   efd = temp.Length();
  406.  
  407.   // Update view system parameters
  408.   BuildTransform();
  409. }
  410.